package com.coin.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.*;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.coin.domain.*;
import com.coin.dto.*;
import com.coin.feign.*;
import com.coin.mapper.*;
import com.coin.service.*;
import com.coin.vo.CashSellParam;
import org.redisson.api.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.*;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * @author 李力
 * @description 针对表【cash_withdrawals(提现表)】的数据库操作Service实现
 * @createDate 2025-06-12 10:12:53
 */
@Service
public class CashWithdrawalsServiceImpl extends ServiceImpl<CashWithdrawalsMapper, CashWithdrawals>
        implements CashWithdrawalsService {

    @Autowired
    private SysMemberFeignClient sysUserFeignClient;

    @Autowired
    private ConfigService configService;

    @Autowired
    private AccountService accountService;

    @Autowired
    private SysMemberFeignClient userBankServiceFeign;

    @Autowired
    private RedissonClient redissonClient;

    @Autowired
    private CashWithdrawAuditRecordMapper cashWithdrawAuditRecordMapper;

    /**
     * @Description: 条件分页查询
     * @Author: 李 力
     * @Date: 2025/6/13
     * @Param:
     * @return: R
     */
    @Override
    public Page<CashWithdrawals> findByPage(Page<CashWithdrawals> page, Long coinId, Long userId, String userName, String mobile, Byte status, String numMin, String numMax, String startTime, String endTime) {
        LambdaQueryWrapper<CashWithdrawals> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper = queryWrapper.eq(coinId != null, CashWithdrawals::getCoinId, coinId)
                .eq(userId != null, CashWithdrawals::getUserId, userId)
                .eq(status != null, CashWithdrawals::getStatus, status)
                .ge(StrUtil.isNotEmpty(numMin), CashWithdrawals::getNum, new BigDecimal(numMin))
                .le(StrUtil.isNotEmpty(numMax), CashWithdrawals::getNum, new BigDecimal(numMax))
                .between(StrUtil.isNotEmpty(startTime) && StrUtil.isNotEmpty(endTime), CashWithdrawals::getCreated, startTime, endTime);
        Map<Long, UserDto> userDtoMap = new HashMap<>();
        if (userId != null || StrUtil.isNotEmpty(userName) || StrUtil.isNotEmpty(mobile)) {
            userDtoMap = sysUserFeignClient.getBasicUsers2(userId == null ? null : Collections.singletonList(userId), userName, mobile);
            if (CollectionUtil.isEmpty(userDtoMap)) {
                return page;
            }
        }
        Page<CashWithdrawals> rechargePage = page(page, queryWrapper);
        List<CashWithdrawals> records = rechargePage.getRecords();
        if (CollectionUtil.isNotEmpty(records)) {
            Map<Long, UserDto> finalUserDtoMap = userDtoMap;
            records.forEach(cashRecharge -> {
                cashRecharge.setUsername(finalUserDtoMap.get(cashRecharge.getUserId()).getUsername());
                cashRecharge.setRealName(finalUserDtoMap.get(cashRecharge.getUserId()).getRealName());
            });
        }
        return rechargePage.setRecords(records);
    }

    /**
     * @Description: GCN的卖出操作
     * @Author: 李 力
     * @Date: 2025/6/19
     * @Param:
     * @return:
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean sell(Long userId, CashSellParam cashSellParam) {
        if (userId == null || cashSellParam == null) {
            throw new RuntimeException("必要参数为空");
        }
        //1.参数校验
        checkCashSellParam(cashSellParam);
        //2.远程调用
        Map<Long, UserDto> userDtoMap = sysUserFeignClient.getBasicUsers2(Collections.singletonList(userId), null, null);
        if (CollectionUtil.isEmpty(userDtoMap)) {
            throw new RuntimeException("无用户信息");
        }
        //3.获取用户信息
        UserBankDto userBankInfo = userBankServiceFeign.getUserBankInfo(userId);
        if (userBankInfo == null) {
            throw new IllegalArgumentException("该用户暂未绑定银行卡信息");
        }
        String remark = RandomUtil.randomNumbers(6);
        // 5 通过数量得到本次交易的金额
        BigDecimal amount = getCashWithdrawalsAmount(cashSellParam.getNum());
        BigDecimal fee = getCashWithdrawalsFee(amount);
        // 7 查询用户的账号ID
        Account account = accountService.findByUserAndCoin(userId, "GCN");
        // 7 订单的创建
        CashWithdrawals cashWithdrawals = new CashWithdrawals();
        cashWithdrawals.setUserId(userId);
        cashWithdrawals.setAccountId(account.getId());
        cashWithdrawals.setCoinId(cashSellParam.getCoinId());
        cashWithdrawals.setStatus((byte) 0);
        cashWithdrawals.setStep((byte) 1);
        cashWithdrawals.setNum(cashSellParam.getNum());
        cashWithdrawals.setMum(amount.subtract(fee)); // 实际金额 = amount-fee
        cashWithdrawals.setFee(fee);
        cashWithdrawals.setBank(userBankInfo.getBank());
        cashWithdrawals.setBankCard(userBankInfo.getBankCard());
        cashWithdrawals.setBankAddr(userBankInfo.getBankAddr());
        cashWithdrawals.setBankProv(userBankInfo.getBankProv());
        cashWithdrawals.setBankCity(userBankInfo.getBankCity());
        cashWithdrawals.setTruename(userBankInfo.getRealName());
        cashWithdrawals.setRemark(remark);
        boolean save = save(cashWithdrawals);
        if (save) {
            accountService.lockUserAmount(userId, cashWithdrawals.getCoinId(), cashWithdrawals.getMum(), "withdrawals_out", cashWithdrawals.getId(), cashWithdrawals.getFee());
        }
        return save;
    }

    private void checkCashSellParam(CashSellParam cashSellParam) {
        // 1 提现状态
        Config cashWithdrawalsStatus = configService.getConfigByCode("WITHDRAW_STATUS");
        if (Integer.parseInt(cashWithdrawalsStatus.getValue()) != 1) {
            throw new IllegalArgumentException("提现暂未开启");
        }
        // 2 提现的金额
        BigDecimal cashSellParamNum = cashSellParam.getNum();
        // 2.1 最小的提现额度100
        Config cashWithdrawalsConfigMin = configService.getConfigByCode("WITHDRAW_MIN_AMOUNT");
        if (cashSellParamNum.compareTo(new BigDecimal(cashWithdrawalsConfigMin.getValue())) < 0) {
            throw new IllegalArgumentException("检查提现的金额");
        }
        // 2.1 最小的提现额度200
        Config cashWithdrawalsConfigMax = configService.getConfigByCode("WITHDRAW_MAX_AMOUNT");
        if (cashSellParamNum.compareTo(new BigDecimal(cashWithdrawalsConfigMax.getValue())) >= 0) {
            throw new IllegalArgumentException("检查提现的金额");
        }
    }

    private BigDecimal getCashWithdrawalsAmount(BigDecimal num) {
        Config rateConfig = configService.getConfigByCode("USDT2CNY");
        return num.multiply(new BigDecimal(rateConfig.getValue())).setScale(2, RoundingMode.HALF_UP);
    }

    private BigDecimal getCashWithdrawalsFee(BigDecimal amount) {
        // 最小的提现费用
        Config withdrawMinPoundage = configService.getConfigByCode("WITHDRAW_MIN_POUNDAGE");
        BigDecimal withdrawMinPoundageFee = new BigDecimal(withdrawMinPoundage.getValue());
        // 提现的费率
        Config withdrawPoundageRate = configService.getConfigByCode("WITHDRAW_POUNDAGE_RATE");
        // 通过费率计算的手续费
        BigDecimal poundageFee = amount.multiply(new BigDecimal(withdrawPoundageRate.getValue())).setScale(2, RoundingMode.HALF_UP);
        //min 取2 个的最小值
        return poundageFee.min(withdrawMinPoundageFee).equals(poundageFee) ? withdrawMinPoundageFee : poundageFee;
    }

    /**
     * @Description: 审核体现记录
     * @Author: 李 力
     * @Date: 2025/6/19
     * @Param:
     * @return: boolean
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateWithdrawalsStatus(Long userId, CashWithdrawAuditRecord record) {
        if (userId == null || record == null) {
            throw new RuntimeException("参数为空");
        }
        RLock lock = redissonClient.getLock("sh:" + record.getId());
        try {
            boolean isOk = lock.tryLock(300, TimeUnit.SECONDS);
            if (isOk) {
                CashWithdrawals cashWithdrawals = getById(record.getId());
                if (cashWithdrawals == null) {
                    throw new IllegalArgumentException("现金的审核记录不存在");
                }
                // 2 添加一个审核的记录
                CashWithdrawAuditRecord cashWithdrawAuditRecordNew = new CashWithdrawAuditRecord();
                cashWithdrawAuditRecordNew.setAuditUserId(userId);
                cashWithdrawAuditRecordNew.setRemark(record.getRemark());
                cashWithdrawAuditRecordNew.setCreated(new Date());
                cashWithdrawAuditRecordNew.setStatus(record.getStatus());
                Integer step = cashWithdrawals.getStep() + 1;
                cashWithdrawAuditRecordNew.setStep(step.byteValue());
                cashWithdrawAuditRecordNew.setOrderId(cashWithdrawals.getId());
                int count = cashWithdrawAuditRecordMapper.insert(cashWithdrawAuditRecordNew);
                if (count > 0) {
                    cashWithdrawals.setStatus(record.getStatus());
                    cashWithdrawals.setRemark(record.getRemark());
                    cashWithdrawals.setLastTime(new Date());
                    cashWithdrawals.setAccountId(userId); //
                    cashWithdrawals.setStep(step.byteValue());
                    boolean updateById = updateById(cashWithdrawals);
                    if (updateById) {
                        Boolean isPass = accountService.decreaseAccountAmount(
                                userId, cashWithdrawals.getUserId(), cashWithdrawals.getCoinId(),
                                cashWithdrawals.getId(), cashWithdrawals.getNum(), cashWithdrawals.getFee(),
                                cashWithdrawals.getRemark(), "withdrawals_out", (byte) 2
                        );
                        return isPass;
                    }
                }
            }
        } catch (Exception exception) {
            exception.printStackTrace();
        } finally {
            lock.unlock();
        }
        return false;
    }

    /**
     * @Description: 查询当前用户的提现记录
     * @Author: 李 力
     * @Date: 2025/6/19
     * @Param:
     * @return: R
     */
    @Override
    public Page<CashWithdrawals> findUserCashRecharge(Page<CashWithdrawals> page, Long userId, Byte status) {
        LambdaQueryWrapper<CashWithdrawals> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper = queryWrapper.eq(userId != null, CashWithdrawals::getUserId, userId)
                .eq(status != null, CashWithdrawals::getStatus, status);
        return page(page, queryWrapper);
    }
}




